import "jquery.easyui";
import "jquery.easyui.columnMenu";
import moment = require("moment");
import { OperableStoreShow } from "logic/database/KeyValuePairsDb";
import Dialog, { DialogStatic, OptionGenerate_BaiscEditSaveDialog } from "logic/page/dialog";
import {
    MDayReviewRecord,
    IReviewRecordController,
    GetCase_IReviewRecordController,
    MReadParam_DayReviewRecord,
    EReviewStatus,
} from "./ReviewRecordController";
import { MStudyItem, IStudyController, GetCase_IStudyController, MReadParam_StudyItem } from "./StudyController";

function GetDaysCycleList(): number[] {
    return [0, 1, 2, 4, 7, 15, 30, 90, 180];
}
interface MPageShow {
    study: MStudyItem;
    review_records: MDayReviewRecord[];
}

interface MParam_PageConfig {
    jquery_datagrid_name: string,
    jquery_search_form_name: string,
}

export class PageShow_Study {
    private readonly param: MParam_PageConfig;
    private readonly study_controller: IStudyController;
    private readonly review_records_controller: IReviewRecordController;

    private readonly day_cycle_list: number[];

    constructor(open_region: OperableStoreShow, param: MParam_PageConfig) {
        this.param = param;
        this.study_controller = GetCase_IStudyController(open_region);
        this.review_records_controller = GetCase_IReviewRecordController(open_region);
        this.day_cycle_list = GetDaysCycleList();
    }

    public GetSearchData(search_form_name: string) {
        let json = $(search_form_name).serializeJSON();
        if (!json) {
            return json;
        }
        for (const key in json) {
            let value = json[key];
            if (value === null || value === undefined || value === "") {
                delete json[key];
            }
        }
        return json;
    }

    public Search(datagrid_name: string, search_form_name: string) {
        let self = this;
        let json = self.GetSearchData(search_form_name);
        $(datagrid_name).datagrid("load", json);
        return false;
    }

    public WriteDataGridConfigs() {
        let self = this;
        let datagrid_name: string = self.param.jquery_datagrid_name;
        let datagrid = $(datagrid_name);


        let columns: JQueryEasyUIOptions.datagrid_column[] = [
            {
                field: "_check_id",
                title: "",
                width: 40,
                checkbox: true,
            },
            {
                hidden: true,
                field: "id",
                title: "数据ID",
                width: 80,
                formatter: (value: object, rowData: MPageShow, rowIndex: number) => {
                    return rowData.study.id;
                },
            },
            {
                field: "type",
                title: "类型",
                width: 120,
                formatter: (value: object, rowData: MPageShow, rowIndex: number) => {
                    return rowData.study.type;
                },
            },
            {
                field: "conent",
                title: "学习内容",
                width: 120,
                formatter: (value: object, rowData: MPageShow, rowIndex: number) => {
                    return rowData.study.conent;
                },
            },
            {
                hidden: true,
                field: "start_time",
                title: "开始学习时间",
                width: 120,
                formatter: (value: object, rowData: MPageShow, rowIndex: number) => {
                    return rowData.study.start_time;
                },
            },
            {
                field: "remark",
                title: "备注内容",
                width: 320,
                formatter: (value: object, rowData: MPageShow, rowIndex: number) => {
                    return rowData.study.remark;
                },
            },
            {
                field: "is_today_need_review",
                title: "是否今日需要复习",
                width: 80,
                formatter: (value: object, rowData: MPageShow, rowIndex: number) => {
                    let item_r_is_today_need_review_day_cycle:number = self.ToResultGet_today_need_review_day_cycle(rowData.study);
                    let is: boolean = item_r_is_today_need_review_day_cycle > -1;
                    return is ? `是(第${item_r_is_today_need_review_day_cycle+1}天)` : "否";
                },
            },
            {
                field: "is_today_reviewed",
                title: "是否今日已复习",
                width: 80,
                formatter: (value: object, rowData: MPageShow, rowIndex: number) => {
                    let item_r_is_today_need_review_day_cycle:number = self.ToResultGet_today_need_review_day_cycle(rowData.study);
                    if (item_r_is_today_need_review_day_cycle == -1) {
                        return "<无需复习>"
                    }
                    let is: boolean = self.ToResult_is_today_reviewed(rowData.review_records);
                    if (is) {
                        return "是";
                    }

                    return "否";
                    // let btn = $(document.createElement("button"));
                    // return btn[0].outerHTML;
                },
            },
        ];
        var cmenu = {};
        datagrid.datagrid({
            toolbar: [
                {
                    iconCls: "icon-application_view_columns",
                    plain: false,
                    text: "展示/隐藏数据列",
                    handler: function () {
                        let target: string = datagrid_name;
                        cmenu[target] = EasyUI_DataGrid_ColumnMenu_Show($(target), cmenu[target]);
                    },
                },
                {
                    iconCls: "icon-add",
                    plain: false,
                    text: "新增",
                    handler: function () {
                        self.Create();
                    },
                },
                {
                    iconCls: "icon-edit",
                    plain: false,
                    text: "修改",
                    handler: function () {
                        self.Edit();
                    },
                },
                {
                    iconCls: "icon-delete",
                    plain: false,
                    text: "删除",
                    handler: function () {
                        self.Remove();
                    },
                },
                {
                    iconCls: "icon-2012080412511",
                    plain: false,
                    text: "写入复习记录",
                    handler: function () {
                        let datagrid_name: string = self.param.jquery_datagrid_name;
                        let row = $(datagrid_name).datagrid("getSelected") as MPageShow;
                        if (!row) {
                            $.messager.alert("提示", "未选择数据！", "info");
                            return;
                        }
                        self.Create_ReviewRecord(row);
                    },
                },
            ],
            iconCls: "icon-application_view_list",
            singleSelect: false,
            fitColumns: true,
            onDblClickRow: (rowIndex: number, rowData: MPageShow) => {
                // self.Create_ReviewRecord(rowData);
                self.Edit();
            },
            onClickRow: function (index: any, row: any) {
                $(this).datagrid("clearSelections");
                $(this).datagrid("selectRow", index);
            },
            onLoadError: function () {
                $.messager.alert("提示", "数据查询发生错误!", "info");
            },
            onLoadSuccess: function (data: any) {},
            columns: [columns],
        } as JQueryEasyUIOptions.datagrid);
    }
    /**
     * 判断结果: 今日需要复习的日期标识
     * @param study 学习内容
     * @returns 日期标识数字 (参数为-1,表示今日不需要复习)
     */
    private ToResultGet_today_need_review_day_cycle(study: MStudyItem): number {
        let self = this;
        if (!study || !study.start_time) {
            throw new Error("学习内容(study)或学习开始时间(start_time)为空");
        }
        let now_time = moment();
        for (let index = 0; index < self.day_cycle_list.length; index++) {
            const day_cycle: number = self.day_cycle_list[index];
            let day_cycle_time = moment(study.start_time).add(day_cycle, "days");
            if (now_time.isSame(day_cycle_time, "day")) {
                return day_cycle;
            }
        }
        return -1;
    }
    /** 判断结果: 是否今日已完成复习 */
    private ToResult_is_today_reviewed(review_record_list: MDayReviewRecord[]): boolean {
        if (!review_record_list || review_record_list.length <= 0) {
            return false;
        }
        let now_time: moment.Moment = moment();
        for (let i = 0; i < review_record_list.length; i++) {
            const record = review_record_list[i];
            if (!record) {
                continue;
            }
            if (record.review_status != EReviewStatus.complate) {
                continue;
            }
            if (!record.review_time) {
                continue;
            }
            if (moment(record.review_time).isSame(now_time, "days")) {
                return true;
            }
        }
        return false;
    }
    public async LoadDataGridData() {
        let self = this;
        $.messager.progress({
            noheader: true,
            title: false,
            msg: "数据加载中...",
            interval: 100,
        });
        // 读取查询条件
        let search_form_name = self.param.jquery_search_form_name;
        let query_param_study: MReadParam_StudyItem = self.GetSearchData(search_form_name);
        let query_result_study: ExecuteResultData<MStudyItem[]> = await self.study_controller.ReadListAsync(query_param_study);
        if (!query_result_study.IsSuccess) {
            $.messager.alert("提示", `查询学习列表出错: ${query_result_study.Message}`, "error");
            return;
        }
        let studys: MStudyItem[] = query_result_study.Data;

        // 查询条件: 是否今日需要复习
        let is_today_need_review: boolean = null;
        if (query_param_study["is_today_need_review"]) {
            is_today_need_review = JSON.parse(query_param_study["is_today_need_review"]);
        }

        // 数据结果
        let rlist: MPageShow[] = [];
        let study_ids: string[] = [];
        for (let i_study = studys.length - 1; i_study >= 0; i_study--) {
            const study = studys[i_study];
            // 判断当天是否需要复习条件
            if (is_today_need_review != null) {
                let item_r_is_today_need_review_day_cycle:number = self.ToResultGet_today_need_review_day_cycle(study);
                let item_r_is_today_need_review:boolean = item_r_is_today_need_review_day_cycle > -1;
                if (item_r_is_today_need_review !== is_today_need_review) {
                    continue;
                }
            }

            // 组合数据
            let m: MPageShow = {
                study: study,
                review_records: null,
            };
            rlist.push(m);
            // 单独记录后续需要处理的内容
            study_ids.push(study.id);
        }


        // 查询条件: 是否今日已完成复习
        let is_today_reviewed: boolean = null;
        if (query_param_study["is_today_reviewed"]) {
            is_today_reviewed = JSON.parse(query_param_study["is_today_reviewed"]);
        }
        let query_param_review_record: MReadParam_DayReviewRecord = {
            study_ids: study_ids,
            review_time_start: moment().format("YYYY-MM-DD 00:00:00"),
            review_time_end: moment().format("YYYY-MM-DD 23:59:59"),
        };
        let query_result_review_record: ExecuteResultData<MDayReviewRecord[]> = await self.review_records_controller.ReadListAsync(query_param_review_record);
        if (!query_result_review_record.IsSuccess) {
            $.messager.alert("提示", `查询复习记录列表出错: ${query_result_review_record.Message}`, "error");
            return;
        }
        let review_record_list: MDayReviewRecord[] = query_result_review_record.Data;
        for (let i_rlist = rlist.length - 1; i_rlist >= 0; i_rlist--) {
            const m = rlist[i_rlist];
            // 筛选获取此学习内容的复习记录
            let m_review_record_list = review_record_list.filter(b => b.study_id == m.study.id);

            // 判断查询条件: 是否今日已完成复习
            if (is_today_reviewed != null) {
                let item_r_is_today_reviewed: boolean = self.ToResult_is_today_reviewed(m_review_record_list);
                if (item_r_is_today_reviewed !== is_today_reviewed) {
                    // 与查询条件不符则排除掉
                    rlist.splice(i_rlist, 1);
                }
            }

            // 最后一步赋值
            m.review_records = m_review_record_list;
        }

        // 渲染加载
        let datagrid_name = self.param.jquery_datagrid_name;
        $.messager.progress("close");
        $(datagrid_name).datagrid("loadData", rlist);
    }

    private EditLock_Save: boolean = false;
    private Create() {
        let self = this;
        let model = {};
        self.UpdateOpen(model, true);
    }
    private async Edit() {
        let self = this;
        let datagrid_name: string = self.param.jquery_datagrid_name;
        let row = $(datagrid_name).datagrid("getSelected") as MPageShow;
        if (!row) {
            $.messager.alert("提示", "未选择数据！", "info");
            return;
        }
        let model: MStudyItem = row.study;
        self.UpdateOpen(model, false);
    }
    private async UpdateOpen(model: {}, is_new_create: boolean) {
        let self = this;
        let conf: OptionGenerate_BaiscEditSaveDialog = {
            title: (is_new_create ? "新增" : "编辑") + "学习知识点",
            url: "PageShow_StudyEdit.html",
            style: {
                width: "450px",
                // "height": "80%",
                padding: "10px 20px 0",
            },
            loadFunc: (dialog: Dialog) => {
                let form = dialog.GetDialog().find("form.edit_form");
                model = formatPrintModelContent(model);
                model["_configs"] = {
                    type_list: self.ToSelectMapItemTextList(self.study_controller.GetTypeList()),
                };
                form.form("load", model);
            },
            isSave: true,
            saveFunc: (dialog: Dialog) => {
                self.UpdateSave(dialog, () => {
                    self.LoadDataGridData();
                });
            },
            closeFunc: (_) => {},
        };
        DialogStatic.ToGenerate_BaiscEditSaveDialog(conf).Create().Open();
    }
    private ToSelectMapItemTextList(text_list: string[]): MSelectMapItem[] {
        if (!text_list || text_list.length <= 0) {
            return [];
        }
        let rlist: MSelectMapItem[] = [];
        for (let i = 0; i < text_list.length; i++) {
            const text = text_list[i];
            rlist.push({
                Text: text,
                Value: i,
            });
        }
        return rlist;
    }

    private async UpdateSave(dialog: Dialog, success_callback: () => void) {
        let self = this;
        let form = dialog.GetDialog().find("form.edit_form");
        form.form("submit", {
            onSubmit: function () {
                $(this).form("enableValidation");
                return false;
            },
        });
        if (!form.form("validate")) {
            return;
        }
        let model: MStudyItem = form.serializeJSON() as MStudyItem;
        model = formatPrintModelContent(model);
        console.log("save.model:", model);
        if (self.EditLock_Save) {
            console.info("正在保存编辑内容, 锁定中...");
            return;
        }
        $.messager.progress({
            noheader: true,
            title: false,
            msg: "正在保存中...",
            interval: 100,
        });
        self.EditLock_Save = true;
        let result: ExecuteResult = await self.study_controller.CreateOrUpdateAsync(model);
        self.EditLock_Save = false;
        $.messager.progress("close");
        if (!result.IsSuccess) {
            $.messager.alert({
                title: "提示",
                msg: ToMessage(result),
                icon: "error",
            });
            return;
        }
        $.messager.alert({
            title: "提示",
            msg: ToMessage(result),
            icon: "success",
        });
        dialog.Close();
        if (success_callback) {
            success_callback();
        }
    }
    private async Remove() {
        let self = this;
        let datagrid_name: string = self.param.jquery_datagrid_name;
        let rows = $(datagrid_name).datagrid("getSelections") as MPageShow[];
        if (!rows.length) {
            $.messager.alert({
                title: "提示",
                msg: "请选择要删除的项。",
                icon: "info",
            });
            return;
        }
        if (
            !(await new Promise((resolve, reject) =>
                $.messager.confirm("提示", "确认删除选中的项？", (r) => resolve(r))
            ))
        ) {
            return;
        }
        let ids: string[] = [];
        for (let i_row = 0; i_row < rows.length; i_row++) {
            const r = rows[i_row];
            ids.push(r.study.id);
        }
        $.messager.progress({
            noheader: true,
            title: false,
            msg: "正在删除中...",
            interval: 100,
        });
        let result: ExecuteResult = await self.study_controller.DeletesAsync(ids);
        $.messager.progress("close");
        if (!result.IsSuccess) {
            $.messager.alert({
                title: "提示",
                msg: ToMessage(result),
                icon: "error",
            });
            return;
        }
        $(datagrid_name).data("SelectIndex", $(datagrid_name).datagrid("getRowIndex", rows[0]));
        $(datagrid_name).data("onLoadSuccessAfter", function () {
            $(datagrid_name).datagrid("clearSelections");
        });
        self.LoadDataGridData();
        $.messager.alert({
            title: "提示",
            msg: ToMessage(result),
            icon: "success",
        });
    }

    private Create_ReviewRecord(rowData: MPageShow) {
        let self = this;

        let item_r_is_today_need_review_day_cycle:number = self.ToResultGet_today_need_review_day_cycle(rowData.study);
        if (item_r_is_today_need_review_day_cycle <= -1) {
            $.messager.alert("提示", "当前内容并不需要复习!", "warning");
            return;
        }
        if (self.ToResult_is_today_reviewed(rowData.review_records)) {
            $.messager.alert("提示", "今日已复习完成, 不要重复写入!", "warning");
            return;
        }
        let review_record_m: MDayReviewRecord = {
            id: null,
            study_id: rowData.study.id,
            day_cycle: self.ToResultGet_today_need_review_day_cycle(rowData.study),
            review_status: EReviewStatus.complate,
            review_time: null,
        };
        self.UpdateOpen_ReviewRecord(review_record_m, true);
    }
    private async UpdateOpen_ReviewRecord(model: MDayReviewRecord, is_new_create: boolean) {
        let self = this;
        let conf: OptionGenerate_BaiscEditSaveDialog = {
            title: (is_new_create ? "新增" : "编辑") + "学习知识点",
            url: "ReviewRecordEdit.html",
            style: {
                width: "450px",
                // "height": "80%",
                padding: "10px 20px 0",
            },
            loadFunc: (dialog: Dialog) => {
                let form = dialog.GetDialog().find("form.edit_form");
                model = formatPrintModelContent(model);
                model["_configs"] = {
                    day_cycle_list: self.GetConfigSelectValueList_day_cycle(),
                    review_status_list: self.GetConfigSelectValueList_review_status(),
                };
                form.form("load", model);
            },
            isSave: true,
            saveFunc: (dialog: Dialog) => {
                self.UpdateSave_ReviewRecord(dialog, () => {
                    self.LoadDataGridData();
                });
            },
            closeFunc: (_) => {},
        };
        DialogStatic.ToGenerate_BaiscEditSaveDialog(conf).Create().Open();
    }
    private GetConfigSelectValueList_day_cycle(): MSelectMapItem[] {
        let self = this;
        let rlist = [];
        for (let i = 0; i < self.day_cycle_list.length; i++) {
            const element = self.day_cycle_list[i];
            rlist.push({
                Text: `第${element+1}天`,
                Value: element,
            } as MSelectMapItem);
        }
        return rlist;
    }
    private GetConfigSelectValueList_review_status(): MSelectMapItem[] {
        let rlist: MSelectMapItem[] = [{
            Text: "未知",
            Value: 0,
        }, {
            Text: "复习完成",
            Value: 1,
        }]
        return rlist;
    }
    private async UpdateSave_ReviewRecord(dialog: Dialog, success_callback: () => void) {
        let self = this;
        let form = dialog.GetDialog().find("form.edit_form");
        form.form("submit", {
            onSubmit: function () {
                $(this).form("enableValidation");
                return false;
            },
        });
        if (!form.form("validate")) {
            return;
        }
        let model: MDayReviewRecord = form.serializeJSON() as MDayReviewRecord;
        model = formatPrintModelContent(model);
        console.log("save.model:", model);
        if (self.EditLock_Save) {
            console.info("正在保存编辑内容, 锁定中...");
            return;
        }
        $.messager.progress({
            noheader: true,
            title: false,
            msg: "正在保存中...",
            interval: 100,
        });
        self.EditLock_Save = true;
        let result: ExecuteResult = await self.review_records_controller.CreateOrUpdateAsync(model);
        self.EditLock_Save = false;
        $.messager.progress("close");
        if (!result.IsSuccess) {
            $.messager.alert({
                title: "提示",
                msg: ToMessage(result),
                icon: "error",
            });
            return;
        }
        $.messager.alert({
            title: "提示",
            msg: ToMessage(result),
            icon: "success",
        });
        dialog.Close();
        if (success_callback) {
            success_callback();
        }
    }
}

/**
 * 格式化输出数据模型的值内容
 * @param model
 */
function formatPrintModelContent(model: any) {
    if (!model) {
        return model;
    }
    if (typeof model !== "object") {
        return model;
    }
    // 格式化内容核心方法
    function formatValue(value: string) {
        if (typeof value === "object") {
            value = formatPrintModelContent(value);
        } else if (typeof value === "string") {
            // 时间格式判断
            if (
                /\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}/gi.test(value) ||
                /\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}.\d{1,3}/gi.test(value)
            ) {
                value = value.replace("T", " ");
            }
        }
        return value;
    }

    // 数组处理
    if (model instanceof Array) {
        var arr = [];
        for (var i = 0; i < model.length; i++) {
            var value = model[i];
            value = formatValue(value);
            arr.push(value);
        }
        return arr;
    }
    // Json对象处理
    var result = {};
    for (var key in model) {
        var value = model[key];
        value = formatValue(value);
        result[key] = value;
    }
    return result;
}

function ToMessage(r: ExecuteResult): string {
    if (r.Message) {
        return r.Message;
    }
    if (r.IsSuccess) {
        return "执行成功!";
    } else {
        return "执行失败!";
    }
}
